package IxDLabIdentity;

import java.util.ArrayList;

import processing.core.*;
import processing.opengl.*;

@SuppressWarnings({ "serial", "unused" })
public class GenerativeBackrgound04 extends PApplet {
	// Get screen resolution
	public final int WIDTH = 1200;
	public final int HEIGHT = 600;

	// Set default background
	public final int BACKGROUNDCOLOR = color(232, 230, 225);
	
	private int goldenRatioNumber = Box.GOLDENRATIONUMBERS.length / 2;
	private int lastGoldenRatioNumber = Box.GOLDENRATIONUMBERS.length / 2;
	private int goldenNumberRatioSum = 0;
	
	private ArrayList<Box> boxes;

	public void setup() {
		size(WIDTH, HEIGHT, OPENGL);
		background(BACKGROUNDCOLOR);
		
		noStroke();
		
		boxes = new ArrayList<Box>();
		
		int colorPos = 0;
		int lastColorPos = 0;

		while (goldenNumberRatioSum < HEIGHT) {
			while (goldenRatioNumber == lastGoldenRatioNumber) {
				goldenRatioNumber = Box.GOLDENRATIONUMBERS[Box.GOLDENRATIONUMBERS.length / 2 + (int) (random(Box.GOLDENRATIONUMBERS.length / 2))];
			}

			int rectX = goldenNumberRatioSum;
			int rectY = HEIGHT - goldenNumberRatioSum - goldenRatioNumber;
			int rectWidth = goldenRatioNumber;
			int rectHeight = Box.calculateBoxHeight(rectWidth);

			while (colorPos == lastColorPos) {
				colorPos = floor(random(Box.COLORARRAYLENGTH));
			}
			
			Box b = new Box(this, rectX, rectY, rectWidth, rectHeight, colorPos);
			
			boxes.add(b);

			goldenNumberRatioSum += goldenRatioNumber;
			lastGoldenRatioNumber = goldenRatioNumber;
			lastColorPos = colorPos;
		}
		goldenNumberRatioSum = 0;
		while (goldenNumberRatioSum < HEIGHT) {
			while (goldenRatioNumber == lastGoldenRatioNumber) {
				goldenRatioNumber = Box.GOLDENRATIONUMBERS[Box.GOLDENRATIONUMBERS.length / 2 + (int) (random(Box.GOLDENRATIONUMBERS.length / 2))];
			}

			int rectX = goldenNumberRatioSum;
			int rectY = HEIGHT - goldenNumberRatioSum - goldenRatioNumber;
			int rectWidth = goldenRatioNumber;
			int rectHeight = Box.calculateBoxHeight(rectWidth);

			while (colorPos == lastColorPos) {
				colorPos = floor(random(Box.COLORARRAYLENGTH));
			}
			
			Box b = new Box(this, rectX, rectY, rectWidth, rectHeight, colorPos);
			
			boxes.add(b);

			goldenNumberRatioSum += goldenRatioNumber;
			lastGoldenRatioNumber = goldenRatioNumber;
			lastColorPos = colorPos;
		}
	}

	public void draw() {
		blendMode(BLEND);
		background(BACKGROUNDCOLOR);
		
		for(Box b: boxes) {
			b.update();
		}
		
		pushMatrix();
		translate(WIDTH / 2, - HEIGHT / 2);
		rotateZ(PConstants.PI / 4);		
		
		for(Box b: boxes) {
			b.draw();
		}
		
		popMatrix();
		
		save("data/background2.jpg");
		noLoop();
	}

	/*** Event handlers ***/
	public void mousePressed() {
		if (mouseButton == LEFT) {
		} else if (mouseButton == RIGHT) {
		} else {
		}
	}

	public void mouseReleased() {
	}

	public void mouseMoved() {
	}

	public void mouseDragged() {
	}

	public void keyPressed() {
	}
}

class Box {	
	public static final int[] GOLDENRATIONUMBERS = {7, 10, 17, 27, 44};
	public static final int MINLENGTH = 2;
	public static final  int MAXLENGTH = 4;
	
	public static final int COLORARRAYLENGTH = 5;	
	public static final float[] REDS = { 17f, 2f, 138f, 0f, 64f };
	public static final float[] GREENS = { 132f, 156f, 73f, 164f, 152f};
	public static final float[] BLUES = { 196f, 162f, 156f, 197f, 180f};
	public static final int BEGINALPHA = 120;
	public static final int ENDALPHA = 0;
	
	public PApplet p;
	
	public int boxX;
	public int boxY;
	public int boxWidth;
	public int boxHeight;
	
	public int boxColorNum;
	public int boxColor;
	public int boxColorAlphaZero;
	
	public boolean isDown = false;
	
	private boolean drawBox = false;
	
	private Box child = null;
	private Box childOther = null;
	private double childLikelihood = 1d;
	
	public Box(PApplet parent, int x, int y, int w, int h, int c, boolean down) {
		p = parent;
		
		boxX = x;
		boxY = y;
		boxWidth = w;
		boxHeight = h;
		
		boxColorNum = c;

		float rectRed = REDS[boxColorNum];
		float rectGreen = GREENS[boxColorNum];
		float rectBlue = BLUES[boxColorNum];

		int beginAlpha = 20 + (int) ((float) (BEGINALPHA - 20) * (1f - (float) x / (float) p.height));
		
		boxColor = p.color(rectRed, rectGreen, rectBlue, beginAlpha);
		boxColorAlphaZero = p.color(rectRed, rectGreen, rectBlue, ENDALPHA);
		
		isDown = down;
		
	}
	
	public Box(PApplet parent, int x, int y, int w, int h, int c) {
		this(parent, x, y, w, h, c, false);
			
		if(Math.random() < 0.5) {
			isDown = true;
		}		
	}
	
	public void update() {		
		if(Math.random() < childLikelihood && boxWidth > GOLDENRATIONUMBERS[0]) {
			int pos = 0;
			
			while(GOLDENRATIONUMBERS[pos] < boxWidth) {
				pos++;
			}
			
			int heightRatio = boxHeight / boxWidth;
			int heightStep = 1 + (int) Math.floor(Math.random() * heightRatio - 1);
			
			int tempX = boxX;
			int tempY = boxY + heightStep * boxWidth;
			
			int tempWidth = GOLDENRATIONUMBERS[pos - 1];
			int tempHeight = calculateBoxHeight(tempWidth);
			
			int tempColorPos = 0;
			while (tempColorPos == boxColorNum) {
				tempColorPos = PApplet.floor(p.random(COLORARRAYLENGTH));
			}	
			
			child = new Box(p, tempX, tempY, tempWidth, tempHeight, tempColorPos, !isDown);
			
			tempX = boxX - tempWidth * (int) Math.floor(Math.random() * heightRatio / 2);
			tempY = boxY;
			
			tempHeight = calculateBoxHeight(tempWidth);
			
			tempColorPos = 0;
			while (tempColorPos == boxColorNum) {
				tempColorPos = PApplet.floor(p.random(COLORARRAYLENGTH));
			}	
			
			childOther = new Box(p, tempX, tempY, tempWidth, tempHeight, tempColorPos, isDown);
			
		}
		
		if(child != null) {
			child.update();
		}		
		if(childOther != null) {
			childOther.update();
		}
	}


	public void draw() {
		p.pushMatrix();
		
		p.translate(boxX, boxY);
		
		if(drawBox) {
			p.beginShape(PConstants.QUADS);
			p.noFill();
			p.stroke(0, 100);
			p.vertex(0, 0);
			p.vertex(0, boxWidth);
			p.vertex(boxWidth, boxWidth);
			p.vertex(boxWidth, 0);
			p.endShape(PConstants.CLOSE);			
		}
		
		if(!isDown) {
			p.pushMatrix();
			p.translate(0, boxWidth);
			p.rotateZ(- PConstants.PI / 2);
		}
		
		p.beginShape(PConstants.QUADS);
		p.fill(boxColor);
		p.noStroke();
		p.vertex(0, 0);
		p.fill(boxColorAlphaZero);
		p.vertex(0, boxHeight);
		p.vertex(boxWidth, boxHeight);
		p.fill(boxColor);
		p.vertex(boxWidth, 0);
		p.endShape(PConstants.CLOSE);

		if(!isDown) {
			p.popMatrix();
		}
		
		p.popMatrix();
		
		if(child != null) {
			child.draw();
		}	
		if(childOther != null) {
			childOther.draw();
		}
	}
	
	public static int calculateBoxHeight(int width) {
		int factor = (int) Math.floor(MINLENGTH + Math.random() * MAXLENGTH);
		
		return width * factor;
	}
}